package com.iot.core.utils;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.ReentrantLock;

public class UUIDUtils {
    private static boolean IS_THREADLOCALRANDOM_AVAILABLE = false;
    private static Random random;
    private static final long leastSigBits;
    private static final ReentrantLock lock = new ReentrantLock();
    private static long lastTime;

    private UUIDUtils() {
    }

    public static String random() {
        byte[] randomBytes = new byte[16];
        if (IS_THREADLOCALRANDOM_AVAILABLE) {
            ThreadLocalRandom.current().nextBytes(randomBytes);
        } else {
            random.nextBytes(randomBytes);
        }

        long mostSigBits = 0L;

        for(int i = 0; i < 8; ++i) {
            mostSigBits = mostSigBits << 8 | (long)(randomBytes[i] & 255);
        }

        long leastSigBits = 0L;

        for(int i = 8; i < 16; ++i) {
            leastSigBits = leastSigBits << 8 | (long)(randomBytes[i] & 255);
        }

        return (new UUID(mostSigBits, leastSigBits)).toString().replaceAll("-", "");
    }

    public static String create() {
        long timeMillis = System.currentTimeMillis() * 10000L + 122192928000000000L;
        lock.lock();

        try {
            if (timeMillis > lastTime) {
                lastTime = timeMillis;
            } else {
                timeMillis = ++lastTime;
            }
        } finally {
            lock.unlock();
        }

        long mostSigBits = timeMillis << 32;
        mostSigBits |= (timeMillis & 281470681743360L) >> 16;
        mostSigBits |= 4096L | timeMillis >> 48 & 4095L;
        return (new UUID(mostSigBits, leastSigBits)).toString().replaceAll("-", "");
    }

    static {
        try {
            IS_THREADLOCALRANDOM_AVAILABLE = null != UUIDUtils.class.getClassLoader().loadClass("java.util.concurrent.ThreadLocalRandom");
        } catch (ClassNotFoundException var1) {
            ;
        }

        byte[] seed = (new SecureRandom()).generateSeed(8);
        leastSigBits = (new BigInteger(seed)).longValue();
        if (!IS_THREADLOCALRANDOM_AVAILABLE) {
            random = new Random(leastSigBits);
        }

    }

    public static void main(String[] args) {
        System.out.println(create());
    }
}
